/*

Miranda IM: the free IM client for Microsoft* Windows*

Copyright 2000-2007 Miranda ICQ/IM project, 
all portions of this codebase are copyrighted to the people 
listed in contributors.txt.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or ( at your option ) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
aLONG with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#include "commonheaders.h"

char *mir_strncpy( char *pszDest, const char *pszSrc, const int cchDest )
{
	if( !pszDest || !pszSrc || !cchDest )
		return NULL;
#if ( _STRSAFE_USE_SECURE_CRT == 1 )
	pszDest = strcpy_s( pszDest, cchDest, pszSrc );
#else
	pszDest = strncpy( pszDest, pszSrc, cchDest-1 );
	pszDest[cchDest-1] = 0;
#endif
	return pszDest;
}

wchar_t *mir_wcsncpy( wchar_t *pszDest, const wchar_t *pszSrc, const int cchDest )
{
	if( !pszDest || !pszSrc || !cchDest )
		return NULL;
#if ( _STRSAFE_USE_SECURE_CRT == 1 )
	pszDest = wcscpy_s( pszDest, cchDest, pszSrc );
#else
	pszDest = wcsncpy( pszDest, pszSrc, cchDest-1 );
	pszDest[cchDest-1] = 0;
#endif
	return pszDest;
}

char *mir_strncat( char *pszDest, const char *pszSrc, const int cchDest )
{
	if( !pszDest || !pszSrc || !cchDest )
		return NULL;
#if ( _STRSAFE_USE_SECURE_CRT == 1 )
	pszDest = strcat_s( pszDest, cchDest, pszSrc );
#else
	strncat( pszDest, pszSrc, cchDest-1 );
	pszDest[cchDest-1] = 0;
#endif
	return pszDest;
}

wchar_t *mir_wcsncat( wchar_t *pszDest, const wchar_t *pszSrc, const int cchDest )
{
	if( !pszDest || !pszSrc || !cchDest )
		return NULL;
#if ( _STRSAFE_USE_SECURE_CRT == 1 )
	pszDest = wcscat_s( pszDest, cchDest, pszSrc );
#else
	pszDest = wcsncat( pszDest, pszSrc, cchDest-1 );
	pszDest[cchDest-1] = 0;
#endif
	return pszDest;
}

char *mir_strncat_c( char *pszDest, const char cSrc ) {
	size_t size = sizeof(char) * (strlen(pszDest) + 2);
	pszDest = (char *) mir_realloc(pszDest, size);
	pszDest[size-2] = cSrc;
	pszDest[size-1] = 0;
	return pszDest;
}

wchar_t	*	mir_wcsncat_c( wchar_t *pwszDest, const wchar_t wcSrc) {
	size_t size = sizeof(wchar_t) * (wcslen(pwszDest) + 2);
	pwszDest = (wchar_t *) mir_realloc(pwszDest, size);
	pwszDest[size-2] = wcSrc;
	pwszDest[size-1] = 0;
	return pwszDest;
}

char *mir_strncat( char *pszDest, const char *pszSrc ) {
	size_t size = sizeof(char) * (strlen(pszDest) + strlen(pszSrc) + 1);
	pszDest = (char *) mir_realloc(pszDest, size);
	strcat(pszDest, pszSrc);
	pszDest[size-1] = 0;
	return pszDest;
}

wchar_t *mir_wcsncat( wchar_t *pwszDest, const wchar_t *pwszSrc ) {
	size_t size = sizeof(wchar_t) * (wcslen(pwszDest) + wcslen(pwszSrc) + 1);
	pwszDest = (wchar_t *) mir_realloc(pwszDest, size);
	wcscat(pwszDest, pwszSrc);
	pwszDest[size-1] = 0;
	return pwszDest;
}

char *mir_strnerase( char *pszDest, size_t sizeFrom, size_t sizeTo ) {
	char *pszReturn = NULL;
	size_t sizeNew, sizeLen = strlen(pszDest);
	if( sizeFrom >= 0 && sizeFrom < sizeLen && sizeTo >= 0 && sizeTo <= sizeLen && sizeFrom < sizeTo ) {
		sizeNew = sizeLen - (sizeTo - sizeFrom);
		size_t sizeCopy = sizeNew - sizeFrom;
		pszReturn = ( char * ) mir_alloc(sizeNew + 1);
		memcpy(pszReturn, pszDest, sizeFrom);
		memcpy(pszReturn + sizeFrom, pszDest + sizeTo, sizeCopy);
		pszReturn[sizeNew] = 0;
	}

	pszDest = (char *) mir_realloc(pszDest, sizeNew + 1);
	pszDest = mir_strcpy(pszDest, pszReturn);
	mir_free(pszReturn);
	return pszDest;
}

wchar_t * mir_wcsdup( const wchar_t * str )
{
   if( str != NULL ) {
		int len = wcslen( str );

		if( len > 0 ) {
			wchar_t *p = ( wchar_t* )mir_alloc( sizeof( WCHAR ) * ( len + 1 ) );
			return mir_wcsncpy( p, str, len + 1 );
		}
   }
   return NULL;
}

int mir_vsnprintfW( wchar_t *pszDest, const int cchDest, const wchar_t *pszFormat, va_list& argList )
{
	int iRet, cchMax;

	if( !pszDest || !pszFormat || !*pszFormat )
		return -1;

	cchMax = cchDest - 1;
#if ( _STRSAFE_USE_SECURE_CRT == 1 )
	iRet = _vsnwprintf_s( pszDest, cchDest, cchMax, pszFormat, argList );
#else
	iRet = _vsnwprintf( pszDest, cchMax, pszFormat, argList );
#endif
	if( iRet < 0 ) pszDest[0] = 0;
	else if( iRet >= cchMax ) {
		pszDest[cchMax] = 0;
		iRet = cchMax;
	}
	return iRet;
}

int mir_snprintfW( wchar_t *pszDest, const int cchDest, const wchar_t *pszFormat, ... )
{
	int iRet;
	va_list argList;

	va_start( argList, pszFormat );
	iRet = mir_vsnprintfW( pszDest, cchDest, pszFormat, argList );
    va_end( argList );
	return iRet;
}

int mir_vsnprintfA( char *pszDest, const int cchDest, const char *pszFormat, va_list& argList )
{
	int iRet, cchMax;
	char *pfmt = NULL;

	if( !pszDest || !pszFormat || !*pszFormat )
		return -1;

	// convert %S to %s as it is not known by the _vsnprintf function and therefor
	// may compromize security!
	for( char *f = ( char* ) pszFormat; f[0] != 0; f++ )
	{
		if( f[0] == '%' )
		{
			if( f[1] == '%' )
			{
				f++;
			}
			else if( f[1] == 'S' )
			{
				if( !pfmt )
				{
					// new memory for string is only allocated if neccesary
					pfmt = ( char* ) _alloca( strlen( pszFormat ) + 1 );
					strcpy( pfmt, pszFormat );
					f = pfmt + ( f - pszFormat );
				}

				f[1] = 's';
			}
		}
	}
	if( !pfmt )
	{
		pfmt = ( char* )pszFormat;
	}

	cchMax = cchDest - 1;
#if ( _STRSAFE_USE_SECURE_CRT == 1 )
	iRet = _vsnprintf_s( pszDest, cchDest, cchMax, pfmt, argList );
#else
	iRet = _vsnprintf( pszDest, cchMax, pfmt, argList );
#endif
	if( iRet < 0 ) pszDest[0] = 0;
	else if( iRet >= cchMax ) {
		pszDest[cchMax] = 0;
		iRet = cchMax;
	}
	return iRet;
}

int mir_snprintfA( char *pszDest, const int cchDest, const char *pszFormat, ... )
{
	int iRet;
	va_list argList;

	va_start( argList, pszFormat );
	iRet = mir_vsnprintfA( pszDest, cchDest, pszFormat, argList );
    va_end( argList );
	return iRet;
}

